package com.wryyyyy.service.impl;

import com.wryyyyy.entity.Dish;
import com.wryyyyy.entity.Hist;
import com.wryyyyy.entity.User;
import com.wryyyyy.mapper.DishMapper;
import com.wryyyyy.mapper.HistMapper;
import com.wryyyyy.mapper.UserMapper;
import com.wryyyyy.service.RecommendService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

@Slf4j
@Service
public class RecommendServiceImpl implements RecommendService {
	@Resource
	private HistMapper histMapper;
	@Resource
	private DishMapper dishMapper;
	@Resource
	private UserMapper userMapper;
	private String userid = "";
	// 相似用户集合
	private List<List<Object>> similarityUser = null;
	// 推荐所有商品集合
	private List<String> targetRecommendDish = null;
	// 浏览过商品集合
	private List<String> commentedDish = null;
	// 用户在商品浏览集合中的位置
	private int targetUserIndex = 0;
	// 目标用户浏览过的商品
	private List<String> targetUserCommentedDish = null;

	private String[] Dish = null;

	@Override
	public List<Dish> getRecommend(String userid) {
		this.userid = userid;
		// 建立用户数组 除了当前用户外 随机抽取15个用户
		String[] user = new String[16];
		user[0] = this.userid;
		List<User> userList = this.userMapper.getUsers(this.userid);
		System.out.println("user == > " + userList.size());
		for (int i = 0; i < 9; i++) {
			int j = i + 1;
			int tbNum = userList.size();
			if (i < tbNum) {
				user[j] = userList.get(i).getId();
			} else {
				user[j] = "0";
			}
		}
		List<Dish> DishList = this.dishMapper.getAllDish();
		this.Dish = new String[DishList.size()];
		for (int j = 0; j < DishList.size(); j++) {
			this.Dish[j] = DishList.get(j).getId();
		}
		// 建立浏览二维数组 用户浏览了商品 1 未浏览 0 之后计算用户的相似度
		int[][] allUserDishhist = new int[16][DishList.size()];
		for (int i = 0; i < 16; i++) {
			for (int j = 0; j < DishList.size(); j++) {
				String Dishid = this.Dish[j];
				Hist hist = new Hist();
				hist.setUserId(user[i]);
				hist.setDishId(Dishid);
				List<Hist> histList = this.histMapper.getHistByCond(hist);
				if (histList.size() == 0) {
					allUserDishhist[i][j] = 0;
				} else {
					Hist h = histList.get(0);
//					allUserDishhist[i][j] = h.getNum();
				}
			}
		}
		for (int i = 0; i < 16; i++) {
			for (int j = 0; j < DishList.size(); j++) {
				if (j == DishList.size() - 1) {
					System.out.print(allUserDishhist[i][j]);
				} else {
					System.out.print(allUserDishhist[i][j] + " ,");
				}
			}
			System.out.println("");
		}
		this.targetUserCommentedDish = new ArrayList<String>();
		Hist hist = new Hist();
		hist.setUserId(this.userid);
		List<Hist> histList = this.histMapper.getHistByCond(hist);
		for (Hist value : histList) {
			// 转换目标用户商品浏览列表
			this.targetUserCommentedDish.add(value.getDishId());
		}

		// 计算用户相似度，排序
		this.calcUserimilarity(allUserDishhist, DishList.size());
		// 计算商品推荐度，排序
		this.calcRecommendDish(allUserDishhist, DishList.size());
		// 处理推荐商品列表
		this.handleRecommendDish(allUserDishhist, DishList.size());
		String rommendId = "";
		for (int i = 0; i < this.targetRecommendDish.size(); i++) {
			String item = this.targetRecommendDish.get(i);
			if (!commentedDish.contains(item)) {
				if (i == this.targetRecommendDish.size() - 1) {
					rommendId += item;
				} else {
					rommendId += item + ",";
				}
			}
		}
		String[] str = rommendId.split(",");
		List<Dish> goodList = new ArrayList<Dish>();
		if (!"".equals(rommendId)) {
			for (String x : str) {
				System.out.println(x);
				Dish g = this.dishMapper.selectById(x);
				goodList.add(g);
			}
		} else {
			goodList = this.dishMapper.getDishRecommend();
		}
		return goodList;
	}

	private void calcRecommendDish(int[][] allUserDishhist, int DishNum) {
		this.targetRecommendDish = new ArrayList<String>();
		List<List<Object>> recommendDish = new ArrayList<List<Object>>();
		List<Object> recommendGood = null;
		double recommdRate = 0, sumRate = 0;
		for (int i = 0; i < DishNum; i++) {
			recommendGood = new ArrayList<Object>();
			recommendGood.add(i);
			recommdRate = allUserDishhist[Integer.parseInt(similarityUser.get(0).get(0).toString())][i]
					* Double.parseDouble(similarityUser.get(0).get(1).toString())
					+ allUserDishhist[Integer.parseInt(similarityUser.get(1).get(0).toString())][i]
							* Double.parseDouble(similarityUser.get(1).get(1).toString());
			recommendGood.add(recommdRate);
			recommendDish.add(recommendGood);
			sumRate += recommdRate;
		}
		System.out.println("sumRate  == > " + sumRate / DishNum);
		compare(recommendDish);
		for (List<Object> tList : recommendDish) {
			System.out.println(tList.get(1));
		}
		// 大于平均推荐度的商品才有可能被推荐
		for (List<Object> item : recommendDish) {
			if (Double.parseDouble(item.get(1).toString()) > sumRate / DishNum) { // 大于平均推荐度的商品才有可能被推荐
				System.out.println("Dish= = >" + Dish[Integer.parseInt(item.get(0).toString())]);
				this.targetRecommendDish.add(Dish[Integer.parseInt(item.get(0).toString())]);
			}
		}
		for (String x : this.targetRecommendDish) {
			System.out.println("x= = >" + x);
		}
	}

	/**
	 * 把推荐列表中用户已经浏览过的商品剔除
	 */
	private void handleRecommendDish(int[][] allUserDishhist, int dishNum) {
		int[] user2hist = new int[dishNum];
		for (int i = 0; i < 16; i++) {
			System.arraycopy(allUserDishhist[i], 0, user2hist, 0, dishNum);
		}
		commentedDish = new ArrayList<String>();
		for (int i = 0; i < user2hist.length; i++) {
			if (allUserDishhist[0][i] != 0) {
				commentedDish.add(Dish[i]);
			}
		}
	}

	/**
	 * 获取两个最相似的用户
	 */
	private void calcUserimilarity(int[][] allUserDishhist, int DishNum) {
		int[] user2hist = new int[DishNum];
		List<List<Object>> tmpList = new ArrayList<List<Object>>();

		for (int i = 0; i < 16; i++) {
			if (i == targetUserIndex) {
				System.arraycopy(allUserDishhist[i], 0, user2hist, 0, DishNum);
				continue;
			}
			List<Object> userimilarity = new ArrayList<Object>();
			int[] user1hist = new int[DishNum];
			System.arraycopy(allUserDishhist[i], 0, user1hist, 0, DishNum);
			userimilarity.add(i);
			userimilarity.add(calcTwoUserimilarity(user1hist, user2hist, DishNum));
			tmpList.add(userimilarity);
		}
		this.similarityUser = compare(tmpList);
	}

	/**
	 * 根据用户数据，计算用户相似度
	 * 
	 * @param user1hist
	 * @param user2hist
	 * @return
	 */
	private static double calcTwoUserimilarity(int[] user1hist, int[] user2hist, int DishNum) {
		double sum = 0;
		for (int i = 0; i < DishNum; i++) {
			sum += Math.pow(user1hist[i] - user2hist[i], 2);
		}
		return Math.sqrt(sum);
	}

	/**
	 * 集合排序
	 */
	private static List<List<Object>> compare(List<List<Object>> tmpList) {
		for (int i = 0; i < tmpList.size(); i++) {
			for (int j = 0; j < tmpList.size() - i; j++) {
				List<Object> t1 = tmpList.get(i);
				List<Object> t2 = tmpList.get(j);
				if (Double.parseDouble("" + t1.get(1)) > Double.parseDouble("" + t2.get(1))) {
					List<Object> tmp = new ArrayList<Object>();
					tmp = t1;
					tmpList.set(i, t2);
					tmpList.set(j, tmp);
				}
			}
		}
		return tmpList;
	}
}